#pragma once

#include "GalconTypes.h"
#include <QGraphicsScene>
#include <boost/enable_shared_from_this.hpp>
#include "ship.h"
#include "FlightInfoFwd.h"
#include "ShipsArrivedInfoFwd.h"
class Planet;
class Ship;

class GameScene : public QGraphicsScene, public boost::enable_shared_from_this<GameScene>
{
   Q_OBJECT
public:
   // two dimensional array of distances
   typedef std::vector<std::vector<qreal> > Distances;
   // two dimensional array of angles
   typedef std::vector<std::vector<qreal> >  Angles;

public:

   GameScene(PlanetsMapPtr planets, PlayersMapPtr players, PlayerID playerID, Distances distancesBtwPlanets, Angles anglesBtwPlanets, QObject *parent = 0);

   ~GameScene();
   //returns distance between planets p1 and p2
   qreal distance(PlanetID p1, PlanetID p2) const
   {
      return m_distances[p1][p2];
   }
   //returns angle between planets p1 and p2
   qreal angle(PlanetID p1, PlanetID p2) const
   {
      return m_angles[p1][p2];
   }

   void LaunchShips(const FlightInfoPtr);
signals:

   void ShipsLaunched(const FlightInfoPtr);

   void ShipsArrivedToPlanet(const ShipsArrivedInfoPtr);

public slots:

   void updateLinksBtwPlanets(Planet* currentItem);

   void planetClicked(PlanetPtr clickedPlanet);

   void newShipsArrived(ShipPtr, const PlanetPtr, const unsigned int, const PlayerID);

protected:

   virtual void drawBackground(QPainter *painter, const QRectF &rect);

   virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

   virtual void wheelEvent(QGraphicsSceneWheelEvent *event);

private:

   void disconnectSignals();

   // this method performs movement of ships from one planet/planets to another
   void launchShips();

   void init();
   // this method returns selected current player's planets or (selectedItems() - PlayersPlanets) it depends on predicate
   template<typename Predicate>
   void getActuallySelectedPlanets(PlanetsVector& items, Predicate pred);
   // calls method setSelected of each item from items and sets value val
   void selectItems(PlanetsVector& items, bool val);
   // returns true if even one of current player's planet is selected
   bool isCurrentPlayerPlanetsSelected() const;
   // holds last selected planets
   PlanetsVector m_lastSelectedPlanets;
   // planetID to planet map
   PlanetsMapPtrConst m_planets;

   PlayerMapPtrConst m_players;

   QPen m_jointPen;

   const PlayerID m_playerID;

   PlanetPtr m_lastSelectedItem;

   Distances m_distances;
   
   Angles m_angles;
   // last item that emitted signal when mouse hover enter or mouse hover leave event occurred
   Planet* m_currentItem;

   boost::shared_ptr<QGraphicsTextItem> m_percentageText;

   boost::shared_ptr<QBrush> m_backgroundBrush;
   // holds value which corresponds to count of ships in percents that will be launched from
   // one planet to another one
   int m_percentage;
};

typedef boost::shared_ptr<GameScene> GameScenePtr;